#ifndef GRADIENT_H
#define GRADIENT_H

#include <stdint.h>
#include <list>
#include <vector>
#include <stdlib.h>

#define COLOUR_TABLE_ENTRIES 65536 

#define CHANNEL_A 3
#define CHANNEL_R 2
#define CHANNEL_G 1
#define CHANNEL_B 0

union Colour {
	public:
		Colour() {}
		
		Colour(uint8_t na, uint8_t nr, uint8_t ng, uint8_t nb) {
			channel[CHANNEL_A] = na;
			channel[CHANNEL_R] = nr;
			channel[CHANNEL_G] = ng;
			channel[CHANNEL_B] = nb;
		}
		
		Colour(uint8_t nr, uint8_t ng, uint8_t nb) {
			channel[CHANNEL_R] = nr;
			channel[CHANNEL_G] = ng;
			channel[CHANNEL_B] = nb;
			channel[CHANNEL_A] = 255;
		}
		
		inline uint8_t getA() {return channel[CHANNEL_A];}
		inline uint8_t getR() {return channel[CHANNEL_R];}
		inline uint8_t getG() {return channel[CHANNEL_G];}
		inline uint8_t getB() {return channel[CHANNEL_B];}
		
		//inline uint32_t getargb() {return ((uint32_t)a) | (((uint32_t)r) << 8) | (((uint32_t)g) << 16) | (((uint32_t)b) << 24); }
		inline uint32_t getargb() {return argb;}
		
		uint32_t argb;
		uint8_t channel[4];
};

class Gradient : public std::list<Colour> {
	public:
		Gradient() {
			colourTable = NULL;
			colourTableSize = 0;
		}
		
		~Gradient() {
			if (colourTable) {
				delete[] colourTable;
			}
		}
		
		void generateColourTable();
		void freeColourTable() {
			if (colourTable) {
				delete[] colourTable;
				colourTable = NULL;
			}
		}
		
		inline Colour getColour(double mu) {
			return colourTable[(int)(mu * (COLOUR_TABLE_ENTRIES - 1))];	
		}
		Colour getColourSlow(double mu);
		
	private:
		Colour *colourTable;
		size_t colourTableSize;
};

std::vector<Gradient> initGradients();


#endif
